package com.sfeir.server.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.sfeir.client.service.AppService;
import com.sfeir.client.util.Constants;
import com.sfeir.client.util.Utils;
import com.sfeir.server.dao.LevelDao;
import com.sfeir.server.dao.ScoreDao;
import com.sfeir.shared.Level;
import com.sfeir.shared.Score;

/**
 * Application RPC Service implementation
 * 
 * @author Oussama Zoghlami
 * @date 27/12/2011
 * 
 */
public class AppServiceImpl extends RemoteServiceServlet implements AppService {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Override
	public List<Level> getLevels() {
		return new LevelDao().getAll();
	}

	@Override
	public List<Map<String, Object>> getUserLevels() {
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		List<Level> levels = new LevelDao().getAll();

		// get the authenticated user
		UserService userService = UserServiceFactory.getUserService();
		User user = userService.getCurrentUser();

		// load the map
		for (Level level : levels) {
			Map<String, Object> userMap = new HashMap<String, Object>();
			userMap.put(Constants.MAP_LEVEL_KEY, level);
			if (null != user) {
				Score userScore = new ScoreDao().getUserScore(user.getEmail(), level.getOrder());
				if (null != userScore) {
					int starsNb = Utils.getScoreStars(userScore.getScore(), level.getOrder());
					userMap.put(Constants.MAP_SCORE_KEY, userScore.getScore());
					userMap.put(Constants.MAP_STARS_KEY, starsNb);
					userMap.put(Constants.MAP_ISUNLOCKED_KEY, (starsNb == 0) ? 1 : 0);
				} else {
					userMap.put(Constants.MAP_SCORE_KEY, 0);
					userMap.put(Constants.MAP_STARS_KEY, 0);
					userMap.put(Constants.MAP_ISUNLOCKED_KEY, 1);
				}
			} else {
				userMap.put(Constants.MAP_SCORE_KEY, 0);
				userMap.put(Constants.MAP_STARS_KEY, 0);
				userMap.put(Constants.MAP_ISUNLOCKED_KEY, 1);
			}
			result.add(userMap);
		}
		updateNextOpenedLevel(user, result);
		return result;
	}
	
	@Override
	public int saveScore(int levelOrder, int score) {
		UserService userService = UserServiceFactory.getUserService();
		User user = userService.getCurrentUser();
		if (null != user) {
			new ScoreDao().saveUserScore(user.getEmail(), user.getNickname(), levelOrder, score);
		}
		return Utils.getScoreStars(score, levelOrder);
	}
	
	@Override
	public List<Map<String, Object>> getNextToBeat(int level) {
		List<Map<String, Object>> result = new ArrayList<Map<String,Object>>();
		
		// get the authenticated user
		UserService userService = UserServiceFactory.getUserService();
		User user = userService.getCurrentUser();
		
		ScoreDao scoreDao = new ScoreDao();
		if (null != user) {
			Score userScore = scoreDao.getUserScore(user.getEmail(), level);
			int userScr = 0;
			if (null != userScore) {
				userScr = userScore.getScore();
			}
			
			Map<String, Object> userMap = new HashMap<String, Object>();
			userMap.put(Constants.MAP_AUTHENTICATED_USER_BESTSCORE, userScr);
			result.add(userMap);
			
			Map<String, Object> nextToBeatMap = scoreDao.getFirstLowerToScore(level, userScr);
			if (null != nextToBeatMap) {
				result.add(nextToBeatMap);
			}
		}
		
		return result;
	}
	
	/**
	 * @param user
	 * @param result
	 */
	private void updateNextOpenedLevel(User user, List<Map<String, Object>> result) {
		for (Map<String, Object> map : result) {
			if ((Integer) map.get(Constants.MAP_ISUNLOCKED_KEY) == 1) {
				map.put(Constants.MAP_ISUNLOCKED_KEY, 0);
				return ;
			}
		}
	}

	@Override
	public String getNickname() {
		UserService service = UserServiceFactory.getUserService();
		User user = service.getCurrentUser();
		if(user == null) {
			return null;
		}
		return user.getNickname();
	}

	@Override
	public String getLogoutUrl() {
		return UserServiceFactory.getUserService().createLogoutURL("/");
	}

}
